package com.qinggeng.project.system.service.impl;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.qinggeng.common.exception.CustomException;
import com.qinggeng.common.redenvelop.BigDecimalUtil;
import com.qinggeng.common.utils.CalendarAdjustUtils;
import com.qinggeng.common.utils.StringUtils;
import com.qinggeng.framework.config.mq.MQSendUtils;
import com.qinggeng.framework.config.mq.dto.MessageOrderCommissionDTO;
import com.qinggeng.framework.config.mq.dto.MessageOrderSingleltemDTO;
import com.qinggeng.framework.config.mq.dto.MessageOrdersDTO;
import com.qinggeng.framework.config.mq.dto.MessageShareMoneyDTO;
import com.qinggeng.framework.config.mq.enums.MQTypeEnum;
import com.qinggeng.project.api.dto.UserAccountConsumptionDTO;
import com.qinggeng.project.system.domain.*;
import com.qinggeng.project.system.domain.vo.AccountInfoVO;
import com.qinggeng.project.system.dto.SysUserAccountDTO;
import com.qinggeng.project.system.dto.WithdrawalPayDTO;
import com.qinggeng.project.system.mapper.UserAccountMapper;
import com.qinggeng.project.system.mapper.UserAccountRecordOrderMapper;
import com.qinggeng.project.system.service.*;
import com.qinggeng.project.tool.pay.utils.WithDrawalUtils;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class UserAccountServiceImpl implements IUserAccountService {
    @Resource
    private UserAccountMapper userAccountMapper;

    @Resource
    private UserAccountRecordService userAccountRecordService;

    @Autowired
    private IOrdersService ordersService;

    @Resource
    private RedissonClient  redissonClient;

    @Resource
    private DataSourceTransactionManager dataSourceTransactionManager;

    @Resource
    private TransactionDefinition transactionDefinition;

    @Resource
    private IUserActivityService  userActivityService;

    @Resource
    private UserAccountConsumptionMonthService userAccountConsumptionMonthService;

    @Resource
    private UserAccountRecordOrderMapper userAccountRecordOrderMapper;


    @Resource
    private UserAccountConsumptionYearService userAccountConsumptionYearService;



    @Resource
    private UserAccountRecordLotteryMonthService userAccountRecordLotteryMonthService;



    @Resource
    private UserAccountRecordWithdrawalService userAccountRecordWithdrawalService;


    @Resource
    private  WithDrawalUtils withDrawalUtils;



    @Resource
    private UserAccountRecordOrderSingleItemService userAccountRecordOrderSingleItemService;


    @Resource
    private IUserAccountService userAccountService;

    @Autowired
    private MQSendUtils mqSendUtils;

    @Autowired
    private MQSendService mqSendService;


    public static   final  String  USER_ACCOUNT="USER:ACCOUNT:";

    public static   final  String  PAID="20";

    public static   final  String  ZERO="0.00";

    public static   final  String  ONE="1.00";

    public static   final  String  DEFAULT_AMOUNT="100.00";


    public static   final  String  ACTIVITY_LAST_MONTH_PROPORTION_KEY="10002";

    public static   final  String  ACTIVITY_THIS_MONTH_PROPORTION_KEY="10003";

    public static   final  String  ACTIVITY_THIS_YEAR_PROPORTION_KEY="10004";

    public static   final  String  ACTIVITY_THIS_MONTH_LUCK_DRAWURL="10005";

    public static   final  String  ACTIVITY_CHANGE_RULES="10014";


    public static   final  String  ACTIVITY_NOTISITAMONTHLYLOTTERY_VALUE="0";


    public static   final  String  THIS_MONTH_PROPORTION="0.10";

    public static   final  String  THIS_YEAR_PROPORTION="0.20";

    public static   final  String  ACTUAL_PAYMENT="20.00";




    @Override
    public void checkFilterUserAccount(Long userId) {

        if (null == userId){
            throw  new CustomException("userId 爲空");
        }
        //唯一个人账户
        UserAccount  account =  checkUserAccount(userId);
        //个人 每月账户信息
        UserAccountConsumptionMonth userAccountConsumption =new UserAccountConsumptionMonth();
        userAccountConsumption.setUserId(userId);
        userAccountConsumptionMonthService.checkUserAccountConsumption(userAccountConsumption);
        //个人 每年账户
        UserAccountConsumptionYear year =new UserAccountConsumptionYear();
        year.setUserId(userId);
        userAccountConsumptionYearService.checkUserAccountConsumptionYear(year);
    }
    private  UserAccount getUserAccount(Long userId){
        Example example=new Example(UserAccount.class);
        example.createCriteria().andEqualTo("userId",userId);
        UserAccount   userAccount=  userAccountMapper.selectOneByExample(example);
        return  userAccount;
    }

    private  UserAccount checkUserAccount(Long userId){
        UserAccount account=getUserAccount(userId);
        if (account==null){
            account=new UserAccount();
            Date date=new Date();
            account.setUserId(userId);
            account.setCreateTime(date);
            account.setUpdateTime(date);
            userAccountMapper.insertSelective(account);
        }
        return  account;
    }

    @Override
    public boolean addUserAccountMoney(Long messageId,Long userId, String money) {
        checkFilterUserAccount(userId);
        TransactionStatus transactionStatus =null;
        UserAccountRecord record=null;
        try {
            transactionStatus=dataSourceTransactionManager.getTransaction(transactionDefinition);
            record=addUpdateAccountMoney(messageId,userId,money,MQTypeEnum.ADD_ACCOUNT.getType());
            dataSourceTransactionManager.commit(transactionStatus);
        }catch (Exception e){
            dataSourceTransactionManager.rollback(transactionStatus);
            throw  new CustomException(e.getMessage());
        }finally {
            String key=USER_ACCOUNT+userId;
            RLock lock= redissonClient.getLock(key);
            boolean isLock = lock.isLocked();
            if (isLock) {
                lock.forceUnlock();
            }
        }
        return  true;
    }

    @Override
    public boolean pullNewUserAccountMoney(Long messageId,Long userId, String money) {
        checkFilterUserAccount(userId);

        TransactionStatus transactionStatus =null;
        UserAccountRecord record=null;
        try {
            transactionStatus=dataSourceTransactionManager.getTransaction(transactionDefinition);
            record=addUpdateAccountMoney(messageId,userId,money,MQTypeEnum.PULL_NEW_ACCOUNT.getType());
            dataSourceTransactionManager.commit(transactionStatus);
        }catch (Exception e){
            dataSourceTransactionManager.rollback(transactionStatus);
            throw  new CustomException(e.getMessage());
        }finally {
            String key=USER_ACCOUNT+userId;
            RLock lock= redissonClient.getLock(key);
            boolean isLock = lock.isLocked();
            if (isLock) {
                lock.forceUnlock();
            }
        }
        return  true;
    }

    @Override
    public boolean lotteryMonthUserAccountMoney(Long messageId,Long userId, String money, String proportion) {
        checkFilterUserAccount(userId);
        TransactionStatus transactionStatus =null;
        UserAccountRecord record=null;
        try {

            transactionStatus=dataSourceTransactionManager.getTransaction(transactionDefinition);
            record=addUpdateAccountMoney(messageId,userId,money,MQTypeEnum.MONTH_LOTTERY_ACCOUNT.getType());
            //用户月消费转零钱
            UserAccountRecordLotteryMonth month=new UserAccountRecordLotteryMonth();
            month.setMessageId(messageId);
            month.setUserId(userId);
            month.setProportion(new BigDecimal(proportion));
            month.setMoney(new BigDecimal(money));
            month.setType(MQTypeEnum.MONTH_LOTTERY_ACCOUNT.getType());
            month.setCalculation(1);
            userAccountRecordLotteryMonthService.checkUserAccountRecordLotteryMonth(month);
            UserAccountConsumptionDTO dto=new UserAccountConsumptionDTO();
            dto.setUserId(userId);
            dto.setMoney(money);
            userAccountConsumptionMonthService.goToSmallChange(dto);
            dataSourceTransactionManager.commit(transactionStatus);
        }catch (Exception e){
            dataSourceTransactionManager.rollback(transactionStatus);
            throw  new CustomException(e.getMessage());
        }finally {
            String key=USER_ACCOUNT+userId;
            RLock lock= redissonClient.getLock(key);
            if (lock.isLocked()){
                lock.forceUnlock();
            }

        }
        return  true;
    }

    @Override
    public boolean turntableLotteryMonthUserAccountMoney(Long messageId, Long userId, String money, String proportion) {
        checkFilterUserAccount(userId);
        TransactionStatus transactionStatus =null;
        UserAccountRecord record=null;
        try {
            UserAccountRecordLotteryMonth month=userAccountRecordLotteryMonthService.getUserAccountRecordLotteryMonth(userId);
            if (null==month){
                return  true;
            }
            transactionStatus=dataSourceTransactionManager.getTransaction(transactionDefinition);
            record=addUpdateAccountMoney(messageId,userId,money,MQTypeEnum.MONTH_LOTTERY_ACCOUNT.getType());
            dataSourceTransactionManager.commit(transactionStatus);
        }catch (Exception e){
            dataSourceTransactionManager.rollback(transactionStatus);
            throw  new CustomException(e.getMessage());
        }finally {
            String key=USER_ACCOUNT+userId;
            RLock lock= redissonClient.getLock(key);
            if (lock.isLocked()){
                lock.forceUnlock();
            }

        }
        return  true;
    }

    @Override
    public boolean withdrawal(Long messageId, Long userId, String money, Integer withdrawalType) {
        checkFilterUserAccount(userId);

        TransactionStatus transactionStatus =null;
        UserAccountRecord record=null;
        try {

            transactionStatus= dataSourceTransactionManager.getTransaction(transactionDefinition);
            record=subUpdateAccountMoney(messageId,userId,money,MQTypeEnum.WITHDRAWAL_ACCOUNT.getType());
            UserAccountRecordWithdrawal withdrawal=new UserAccountRecordWithdrawal();
            withdrawal.setMessageId(messageId);
            withdrawal.setUserId(userId);
            withdrawal.setWithdrawalType(withdrawalType);
            withdrawal.setMoney(new BigDecimal(money));
            userAccountRecordWithdrawalService.checkUserAccountRecordWithdrawal(withdrawal);
            WithdrawalPayDTO payDTO =new WithdrawalPayDTO();
            payDTO.setPayNo(messageId.toString());
            payDTO.setType(withdrawalType.toString());
            payDTO.setMoney(money);
            payDTO.setUserId(userId);
            withDrawalUtils.withDrawal(payDTO);
            dataSourceTransactionManager.commit(transactionStatus);
        }catch (Exception e){
            dataSourceTransactionManager.rollback(transactionStatus);
            throw  new CustomException(e.getMessage());
        }finally {
            String key=USER_ACCOUNT+userId;
            RLock lock= redissonClient.getLock(key);
            boolean isLock = lock.isLocked();
            if (isLock) {
                lock.forceUnlock();
            }
        }
        return  true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean shareWithdrawal(Long userId, Long messageId, Integer type,String money) {

        return false;
    }

    @Override
    public boolean orderCommissionAccountMoney(MessageOrderCommissionDTO dto) {
        Long userId=dto.getUserId();
        if (null ==userId){
            throw  new CustomException("orderCommissionAccountMoney userId is  null");
        }
        Long messageId=dto.getMessageId();
        if (null ==messageId){
            throw  new CustomException("orderCommissionAccountMoney messageId is  null");
        }

        String money=dto.getMoney();
        if (new BigDecimal(money).compareTo(BigDecimal.ZERO)<=0){
            throw  new CustomException("orderCommissionAccountMoney money <=  0");
        }
        checkFilterUserAccount(userId);
        TransactionStatus transactionStatus =null;
        UserAccountRecord record=null;
        try {
            transactionStatus=dataSourceTransactionManager.getTransaction(transactionDefinition);
            record=addUpdateAccountMoney(messageId,userId,money,MQTypeEnum.ORDER_COMMISSION_ACCOUNT.getType());
            dataSourceTransactionManager.commit(transactionStatus);
        }catch (Exception e){
            dataSourceTransactionManager.rollback(transactionStatus);
            throw  new CustomException(e.getMessage());
        }finally {
            String key=USER_ACCOUNT+userId;
            RLock lock= redissonClient.getLock(key);
            boolean isLock = lock.isLocked();
            if (isLock) {
                lock.forceUnlock();
            }
        }
        return true;
    }

    @Override
    public boolean shareMoney(MessageShareMoneyDTO dto) {

        Long userId=dto.getUserId();
        if (null ==userId){
            throw  new CustomException("shareMoney userId is  null");
        }
        Long messageId=dto.getMessageId();
        if (null ==messageId){
            throw  new CustomException("shareMoney messageId is  null");
        }

        String money=dto.getMoney();
        if (new BigDecimal(money).compareTo(BigDecimal.ZERO)<=0){
            throw  new CustomException("shareMoney money <=  0");
        }
        checkFilterUserAccount(userId);
        TransactionStatus transactionStatus =null;
        UserAccountRecord record=null;
        try {
            transactionStatus=dataSourceTransactionManager.getTransaction(transactionDefinition);
            UserAccount userAccount=new UserAccount();
            userAccount.setUserId(userId);
            userAccount.setAccount(new BigDecimal(money));
            userAccountMapper.addUserAccountMoney(userAccount);
            record=addUpdateAccountMoney(messageId,userId,money,MQTypeEnum.SHARE_ACCOUNT.getType());
            dataSourceTransactionManager.commit(transactionStatus);
        }catch (Exception e){
            dataSourceTransactionManager.rollback(transactionStatus);
            throw  new CustomException(e.getMessage());
        }finally {
            String key=USER_ACCOUNT+userId;
            RLock lock= redissonClient.getLock(key);
            boolean isLock = lock.isLocked();
            if (isLock) {
                lock.forceUnlock();
            }
        }
        return true;
    }

    @Override
    public boolean subUserAccountMoney(Long messageId,Long userId,String money) {
        checkFilterUserAccount(userId);

        TransactionStatus transactionStatus =null;
        UserAccountRecord record=null;
        try {

            transactionStatus=dataSourceTransactionManager.getTransaction(transactionDefinition);
            record= subUpdateAccountMoney(messageId,userId,money,MQTypeEnum.SUB_ACCOUNT.getType());
            dataSourceTransactionManager.commit(transactionStatus);
        }catch (Exception e){
            dataSourceTransactionManager.rollback(transactionStatus);
            throw  new CustomException(e.getMessage());
        }finally {
            String key=USER_ACCOUNT+userId;
            RLock lock= redissonClient.getLock(key);
            boolean isLock = lock.isLocked();
            if (isLock) {
                lock.forceUnlock();
            }

        }
        return  true;
    }
    @Override
    public boolean redEnvelopesAccountMoney(Long messageId,Long userId, String money) {
        checkFilterUserAccount(userId);

        TransactionStatus transactionStatus =null;
        UserAccountRecord record=null;
        try {

            transactionStatus=dataSourceTransactionManager.getTransaction(transactionDefinition);
            record= addUpdateAccountMoney(messageId,userId,money,MQTypeEnum.RED_ENVRLOPES.getType());
            dataSourceTransactionManager.commit(transactionStatus);
        }catch (Exception e){
            dataSourceTransactionManager.rollback(transactionStatus);
            throw  new CustomException(e.getMessage());
        }finally {
            String key=USER_ACCOUNT+userId;
            RLock lock= redissonClient.getLock(key);
            boolean isLock = lock.isLocked();
            if (isLock) {
                lock.forceUnlock();
            }
        }

        return  true;
    }

    private boolean checkOrdersActualPayment(String ordersNo){

        Orders orders=checkOrder(ordersNo);
        //退款的钱
        BigDecimal sumReturn=userAccountRecordOrderSingleItemService.getSumReturnMoney(ordersNo);
        //实际订单支付的钱
        BigDecimal actualPayment =orders.getPayPrice().subtract(sumReturn).setScale(2,BigDecimal.ROUND_UP);

        return actualPayment.compareTo(new BigDecimal(ACTUAL_PAYMENT))>=0;
    }


    @Override
    public boolean orderPayMoney(Long messageId, String orderNo) {
        Orders orders= checkOrder(orderNo);
        Long userId=orders.getUserId();
        checkFilterUserAccount(userId);
        //金额支付的钱
        BigDecimal payPrice= orders.getPayPrice();
        //退款的钱
        BigDecimal sumReturn=userAccountRecordOrderSingleItemService.getSumReturnMoney(orderNo);
        //实际订单支付的钱
        BigDecimal actualPayment =payPrice.subtract(sumReturn).setScale(2,BigDecimal.ROUND_UP);

        TransactionStatus transactionStatus = null;
        UserAccountRecord record=null;
        try {
            transactionStatus=dataSourceTransactionManager.getTransaction(transactionDefinition);
            record= addUpdateAccountMoneyDoNotOperateAccount(messageId, userId, actualPayment.toString(), MQTypeEnum.ORDER_PAY_ACCOUNT.getType());
            UserAccountConsumptionDTO userAccountConsumptionDTO =new UserAccountConsumptionDTO();
            userAccountConsumptionDTO.setUserId(userId);
            userAccountConsumptionDTO.setMoney(actualPayment.toString());
            if (actualPayment.compareTo(new BigDecimal(ACTUAL_PAYMENT))>=0) {
                boolean bl = userAccountConsumptionMonthService.addUpdateUserAccountConsumption(userAccountConsumptionDTO);
                if (bl==false){
                    throw  new CustomException("订单账户支付金额统计异常");
                }
            }
            boolean bl=insertUserAccountRecordOrder(orderNo,record);
            if (bl ==false){
                throw new   CustomException("订单账本支付记录失败");
            }
            dataSourceTransactionManager.commit(transactionStatus);
        }catch (Exception e){
            dataSourceTransactionManager.rollback(transactionStatus);
            throw  new CustomException(e.getMessage());
        }finally {
            String key=USER_ACCOUNT+userId;
            RLock lock= redissonClient.getLock(key);
            boolean isLock = lock.isLocked();
            if (isLock) {
                lock.forceUnlock();
            }
        }
        return  true;
    }


    @Override
    public boolean orderPayMoney( String orderNo) {
        Long messgaeId=IdUtil.getSnowflake(1L,1L).nextId();
        boolean result=orderPayMoney(messgaeId,  orderNo);
        if(!result){
            return false;
        }
        if(this.checkOrdersActualPayment(orderNo)){
            MessageOrdersDTO ordersDTO=new MessageOrdersDTO();
            ordersDTO.setType(MQTypeEnum.RED_ENVELOPES_MESSAGE_JPUSH.getType());
            ordersDTO.setOrdersNo(orderNo);
            mqSendUtils.sendAsynMessage(ordersDTO);
        }
        return  true;
    }

    private  Orders checkOrder(String orderNo){
        Orders orders = ordersService.selectOrdersByOrdersNo(orderNo);
        if (null == orders) {
            throw  new CustomException("orders 不能为空");
        }
        String payStatus = orders.getPayStatus();
        if (payStatus.equals(PAID) == false) {
            throw  new CustomException("orders 状态不是已经支付状态");
        }
        Long userId = orders.getUserId();
        if (null == userId) {
            throw  new CustomException("userId 不能为空");
        }
        BigDecimal payPrice = orders.getPayPrice();
        if (null == payPrice) {
            throw  new CustomException("payPrice 不能为空");
        }
        return  orders;
    }
    @Override
    public boolean orderRefundMoney(Long messageId, String orderNo) {
        Orders orders= checkOrder(orderNo);
        Long userId=orders.getUserId();
        checkFilterUserAccount(userId);
        BigDecimal getMoney= orders.getPayPrice();
        String key=USER_ACCOUNT+userId;
        RLock lock= redissonClient.getLock(key);
        TransactionStatus  transactionStatus=null;
        UserAccountRecord record=null;
        try {
            transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
            record=  subUpdateAccountMoneyDoNotOperateAccount(messageId,userId,ZERO,MQTypeEnum.ORDER_REFUND_ACCOUNT.getType());
            UserAccountConsumptionDTO userAccountConsumptionDTO =new UserAccountConsumptionDTO();
            userAccountConsumptionDTO.setUserId(userId);
            userAccountConsumptionDTO.setMoney(getMoney.toString());
            boolean bl=userAccountConsumptionMonthService.subUpdateUserAccountConsumption(userAccountConsumptionDTO);
            if (bl==false){
                throw new   CustomException("订单账户退款记录异常");
            }
            bl=insertUserAccountRecordOrder(orderNo,record);
            if (bl ==false){
                throw new   CustomException("订单账单退款记录失败");
            }
            dataSourceTransactionManager.commit(transactionStatus);
        }catch (Exception e){
            dataSourceTransactionManager.rollback(transactionStatus);
            throw  new CustomException(e.getMessage());
        }finally {
            boolean isLock = lock.isLocked();
            if (isLock) {
                lock.forceUnlock();
            }
        }
        return  true;
    }

    @Override
    public String getChange(Long userId) {
        if (null==userId){
            throw  new CustomException("当前用户不存在");
        }
        UserAccount userAccount=getUserAccount(userId);
        if (null == userAccount){
            userAccount=new UserAccount();
            userAccount.setUserId(userId);
            this.checkFilterUserAccount(userId);
            return  ZERO;
        }
        String change=userAccount.getAccount().toString();
        return change;
    }

    private String getChangeRules() {
        UserActivity userActivity=userActivityService.getUserActivity(ACTIVITY_CHANGE_RULES);
        if (null == userActivity){
            return  "";
        }
        return userActivity.getActivityValue();
    }
    private boolean getNotIsItAMonthlyLottery() {
        UserActivity userActivity=userActivityService.getUserActivity(UserActivityServiceImpl.LOTTERY_MONTH_PROPORTION_IS_ACTIVITY);
        //不开起
        if (null == userActivity){
            return  true;
        }
        //开启
        Integer  status=userActivity.getStatus();
        if (ACTIVITY_NOTISITAMONTHLYLOTTERY_VALUE.equals(String.valueOf(status))){
            return  false;
        }
        return  true;
    }



    @Override
    public AccountInfoVO getAccountInfoVO(Long userId) {

        AccountInfoVO accountInfoVO =getAccountInfoVOModel(userId);
        //查询上一个月数据
        UserAccountConsumptionMonth userAccountConsumption =new UserAccountConsumptionMonth();
        userAccountConsumption.setUserId(userId);
        userAccountConsumption.setCreateMonth(CalendarAdjustUtils.getMonthToStr());
        //查看当月消费记录
        UserAccountConsumptionMonth  userAcc=userAccountConsumptionMonthService.getUserAccountConsumption(userAccountConsumption);
        if (null ==userAcc){
            //插入月消费
            userAccountConsumptionMonthService.checkUserAccountConsumption(userAccountConsumption);
            userAccountConsumptionMonthService.updateUserAccountConsumption(userId);
            //获取月消费
            UserAccountConsumptionMonth  month=userAccountConsumptionMonthService.getUserAccountConsumption(userAccountConsumption);
            String thisThisMonth=userAccountService.futureThisMonthConsumption(userId);
            accountInfoVO.setThisMonthConsumption(thisThisMonth);
            accountInfoVO.setLastMonthConsumption(month.getLastMonthConsumption().toString());
            accountInfoVO.setThisMonthCanBeWithdrawn(month.getThisMonthCanBeWifthdrawn().toString());
            //上一个月消费体现金额不是0
            BigDecimal lastMonthCanBeWifthdrawn=getLastMonthCanBeWifthdrawn(userId);
            if (lastMonthCanBeWifthdrawn.compareTo(BigDecimal.ZERO)>0){
                accountInfoVO.setThisMonthCanBeWithdrawn(lastMonthCanBeWifthdrawn.toString());
            }
            accountInfoVO.setThisMonthNeedToConsume(month.getThisMonthNeedToConsume().toString());
            accountInfoVO.setThisMonthLuckDrawUrl(month.getThisMonthLuckDrawUrl());
            accountInfoVO.setThisMonthNeedToConsumePercentage(month.getThisMonthNeedToConsumePercentage().toString());
            return  accountInfoVO;
        }
        accountInfoVO.setThisMonthCanBeWithdrawn(userAcc.getThisMonthCanBeWifthdrawn().toString());
        //上一个月消费体现金额不是0
        BigDecimal lastMonthCanBeWifthdrawn=getLastMonthCanBeWifthdrawn(userId);
        if (lastMonthCanBeWifthdrawn.compareTo(BigDecimal.ZERO)>0){
            accountInfoVO.setThisMonthCanBeWithdrawn(lastMonthCanBeWifthdrawn.toString());
        }
        accountInfoVO.setLastMonthConsumption(userAcc.getLastMonthConsumption().setScale(2, RoundingMode.HALF_UP).toString());
        accountInfoVO.setThisMonthConsumption(userAcc.getThisMonthConsumption().setScale(2, RoundingMode.HALF_UP).toString());
        accountInfoVO.setThisMonthNeedToConsume(userAcc.getThisMonthNeedToConsume().setScale(2, RoundingMode.HALF_UP).toString());
        accountInfoVO.setThisMonthNeedToConsumePercentage(userAcc.getThisMonthNeedToConsumePercentage().toString());
        return accountInfoVO;
    }


    private AccountInfoVO getAccountInfoVOModel(Long userId){

        final AccountInfoVO accountInfoVO = new AccountInfoVO();
        accountInfoVO.setChange(getChange(userId));
        accountInfoVO.setChangeRules(getChangeRules());
        accountInfoVO.setNotIsItAMonthlyLottery(getNotIsItAMonthlyLottery());
        accountInfoVO.setThisMonthLuckDrawUrl(userAccountService.thisMonthLuckDrawUrl());
        accountInfoVO.setLastMonthConsumption(ZERO);
        accountInfoVO.setThisMonthConsumption(ZERO);
        accountInfoVO.setThisMonthNeedToConsume(ZERO);
        accountInfoVO.setThisMonthNeedToConsumePercentage(ZERO);
        accountInfoVO.setThisMonthCanBeWithdrawn(ZERO);
        UserAccountConsumptionYear year=new UserAccountConsumptionYear();
        year.setUserId(userId);
        year.setCreateYear(CalendarAdjustUtils.getYearToStr());
        UserAccountConsumptionYear userAccountConsumptionYear=userAccountConsumptionYearService.getUserAccountConsumptionYear(year);
        if (null==userAccountConsumptionYear){
            accountInfoVO.setThisYearCanBeWithdrawn(ZERO);
            accountInfoVO.setThisYearConsumption(ZERO);
            return  accountInfoVO;
        }
        BigDecimal thisYearConsumption=userAccountConsumptionYear.getThisYearConsumption().setScale(2, RoundingMode.HALF_UP);
        accountInfoVO.setThisYearConsumption(thisYearConsumption.toString());
        String yearWithdrawalProportion=userActivityService.getYearWithdrawalProportion();
        accountInfoVO.setThisYearCanBeWithdrawn(BigDecimalUtil.multiply(thisYearConsumption,new BigDecimal(yearWithdrawalProportion)).toString());
        return  accountInfoVO;
    }

    private  BigDecimal  getLastMonthCanBeWifthdrawn(Long userId){

        UserAccountConsumptionMonth userAccountConsumption =new UserAccountConsumptionMonth();
        userAccountConsumption.setUserId(userId);
        userAccountConsumption.setCreateMonth(CalendarAdjustUtils.getLastMonthToStr());
        UserAccountConsumptionMonth  userAcc=userAccountConsumptionMonthService.getUserAccountConsumption(userAccountConsumption);
        if (null ==userAcc){
            return BigDecimal.ZERO;
        }
        return  userAcc.getThisMonthCanBeWifthdrawn();
    }
    @Override
    public String futureLastMonthConsumption(Long userId) {

        List<UserAccountRecord> lastMonthOrderPayList=userAccountRecordService.listUserAccountOrderPayByLastMonth(userId);
        String lastMonthConsumption=userAccountRecordService.sunMoney(lastMonthOrderPayList);
        return lastMonthConsumption;
    }

    @Override
    public String futureThisMonthConsumption(Long userId) {

        //获取这个月的消费记录 订单完成总结状态时候才计入消费
        List<UserAccountRecord> thisMonthOrderPayList=userAccountRecordService.listUserAccountOrderPayByThisMonth(userId);

        String thisMonthConsumption=userAccountRecordService.sunMoney(thisMonthOrderPayList);

        return thisMonthConsumption;
    }

    @Override
    public String futurthisYearConsumption(Long userId) {

        //今年的消费记录 订单完成总结状态时候才计入消费
        List<UserAccountRecord> thisYearOrderPayList=userAccountRecordService.listUserAccountOrderPayByThisYear(userId);

        String thisYearConsumption=userAccountRecordService.sunMoney(thisYearOrderPayList);
        return thisYearConsumption;

    }

    private UserAccountRecord addUpdateAccountMoney(Long messageId,Long userId,String money,Integer type){
        BigDecimal getMoney=checkMoney(money);
        UserAccount userAcc=getUserAccount(userId);
        final UserAccountRecord userAccountRecord = new UserAccountRecord();
        userAccountRecord.setMessageId(messageId);
        userAccountRecord.setUserId(userId);
        BigDecimal userAccMoeny=userAcc.getAccount();
        //之前金額
        BigDecimal beforeAccount=BigDecimalUtil.subtract(userAccMoeny,getMoney);
        userAccountRecord.setBeforeAccount(beforeAccount);
        //操作金額
        userAccountRecord.setMoney(getMoney);
        //之後金額
        userAccountRecord.setAfterAccount(userAccMoeny);
        userAccountRecord.setType(type);
        String userName=userAcc.getUserName();
        userAccountRecord.setUserName(userName);
        userAcc.setAccount(getMoney);
        boolean bl=userAccountRecordService.insertUserAccountRecord(userAccountRecord);
        if (bl ==false){
            int size= userAccountMapper.subUserAccountMoney(userAcc);
            if (size<1){
                throw  new CustomException("增加賬戶金額失敗");
            }
        }
        return  userAccountRecord;
    }
    private UserAccountRecord addUpdateAccountMoneyDoNotOperateAccount(Long messageId,Long userId,String money,Integer type){
        BigDecimal getMoney=checkMoney(money);
        UserAccount userAcc=getUserAccount(userId);
        final UserAccountRecord userAccountRecord = new UserAccountRecord();
        userAccountRecord.setMessageId(IdUtil.getSnowflake(1L,1L).nextId());
        userAccountRecord.setUserId(userId);
        BigDecimal userAccMoeny=userAcc.getAccount();
        //之前金額
        userAccountRecord.setBeforeAccount(userAccMoeny);
        //操作金額
        userAccountRecord.setMoney(getMoney);
        //之後金額
        userAccountRecord.setAfterAccount(userAccMoeny);
        userAccountRecord.setType(type);
        String userName=userAcc.getUserName();
        userAccountRecord.setUserName(userName);
        userAcc.setAccount(getMoney);
        userAccountRecordService.insertUserAccountRecord(userAccountRecord);
        return  userAccountRecord;
    }

    private  BigDecimal checkMoney(String money){
        BigDecimal d=new BigDecimal(money);
        if ( d.signum()<0){
            throw  new CustomException("金額不能是負數");
        }
        return  d;
    }


    private UserAccountRecord subUpdateAccountMoney(Long messageId,Long userId,String money,Integer type){
        BigDecimal getMoney=checkMoney(money);
        UserAccount userAcc=getUserAccount(userId);
        UserAccountRecord userAccountRecord =new UserAccountRecord();
        userAccountRecord.setMessageId(messageId);
        userAccountRecord.setUserId(userId);
        BigDecimal userAccMoeny=userAcc.getAccount();
        //之前金額
        userAccountRecord.setBeforeAccount(BigDecimalUtil.add(userAccMoeny,getMoney));
        //操作金額
        userAccountRecord.setMoney(getMoney);
        //之後金額
        BigDecimal accMoney=userAccMoeny;
        if (accMoney.signum() <0){
            throw  new CustomException("操作之后金额是负数");
        }
        userAccountRecord.setAfterAccount(accMoney);
        userAccountRecord.setType(type);
        userAccountRecord.setUserName(userAcc.getUserName());
        boolean bl=userAccountRecordService.insertUserAccountRecord(userAccountRecord);
        if (bl ==false){
            userAcc.setAccount(getMoney);
            int size=userAccountMapper.addUserAccountMoney(userAcc);
            if (size<1){
                throw new CustomException("減少賬戶金額失敗");
            }
        }
        return  userAccountRecord;
    }



    private UserAccountRecord subUpdateAccountMoneyDoNotOperateAccount(Long messageId,Long userId,String money,Integer type){
        BigDecimal getMoney=checkMoney(money);
        UserAccount userAcc=getUserAccount(userId);
        UserAccountRecord userAccountRecord =new UserAccountRecord();
        userAccountRecord.setMessageId(messageId);
        userAccountRecord.setUserId(userId);
        BigDecimal userAccMoeny=userAcc.getAccount();
        //之前金額
        userAccountRecord.setBeforeAccount(userAccMoeny);
        //操作金額
        userAccountRecord.setMoney(getMoney);
        //之後金額
        BigDecimal accMoney=userAccMoeny;
        BigDecimal d=accMoney.setScale(2,BigDecimal.ROUND_HALF_UP);
        if ( d.signum()<=0){
            throw  new CustomException("操作之后金额是负数");
        }
        userAccountRecord.setAfterAccount(accMoney);
        userAccountRecord.setType(type);
        userAccountRecord.setUserName(userAcc.getUserName());
        userAccountRecordService.insertUserAccountRecord(userAccountRecord);
        return  userAccountRecord;
    }

    public  BigDecimal thisMonthProportion(){
        UserActivity userActivity=userActivityService.getUserActivity(ACTIVITY_THIS_MONTH_PROPORTION_KEY);
        if (null ==userActivity){
            return  new BigDecimal(THIS_MONTH_PROPORTION);
        }
        String value=userActivity.getActivityValue();
        if (StringUtils.isEmpty(value)){
            return  new BigDecimal(THIS_MONTH_PROPORTION);

        }
        return  new BigDecimal(value);
    }

    public  BigDecimal thisYearProportion(){
        UserActivity userActivity=userActivityService.getUserActivity(ACTIVITY_THIS_YEAR_PROPORTION_KEY);
        if (null ==userActivity){
            return  new BigDecimal(THIS_YEAR_PROPORTION);
        }
        String value=userActivity.getActivityValue();
        if (StringUtils.isEmpty(value)){
            return  new BigDecimal(THIS_MONTH_PROPORTION);
        }
        return  new BigDecimal(value);
    }
    public  BigDecimal thisLastMonthMoney(){
        UserActivity userActivity=userActivityService.getUserActivity(ACTIVITY_LAST_MONTH_PROPORTION_KEY);
        if (null ==userActivity){
            return  new BigDecimal(DEFAULT_AMOUNT);
        }
        String value=userActivity.getActivityValue();
        if (StringUtils.isEmpty(value)){
            return  new BigDecimal(DEFAULT_AMOUNT);

        }
        return  new BigDecimal(value);
    }

    public  String thisMonthLuckDrawUrl(){
        UserActivity userActivity=userActivityService.getUserActivity(ACTIVITY_THIS_MONTH_LUCK_DRAWURL);
        if (null ==userActivity){
            throw  new CustomException("服务未开启");
        }
        String value=userActivity.getActivityValue();
        if (StringUtils.isEmpty(value)){
            throw  new CustomException("抽奖地址未设置");
        }
        return  userActivity.getActivityValue();
    }


    private boolean  insertUserAccountRecordOrder(String orderno,UserAccountRecord userAccountRecord){
        UserAccountRecordOrder userAccountRecordOrder=new UserAccountRecordOrder();
        BeanUtils.copyProperties(userAccountRecord,userAccountRecordOrder);
        userAccountRecordOrder.setOrderNo(orderno);
        return  insertUserAccountRecordOrder(userAccountRecordOrder);
    }

    private boolean  insertUserAccountRecordOrder(UserAccountRecordOrder userAccountRecordOrder){
        return  userAccountRecordOrderMapper.insertSelective(userAccountRecordOrder)>=1;
    }

    @Override
    public boolean orderGoodsSingleLtemRefund(MessageOrderSingleltemDTO dto) {
        Long userId=dto.getUserId();
        checkFilterUserAccount(userId);
        String orderNo=dto.getOrderNo();
        Long ordersGoodsId=dto.getOrdersGoodsId();
        String money= dto.getMoney();
        Integer type=dto.getType();
        String key=USER_ACCOUNT+userId;
        RLock lock= redissonClient.getLock(key);
        TransactionStatus transactionStatus =null;
        UserAccountRecord record=null;
        try {
            /*String result= withDrawalUtils.refund(orderNo,ordersGoodsId,new BigDecimal(money));
            JSONObject jsonObject=JSONObject.parseObject(result);
            if (!jsonObject.getString("return_code").equals("SUCCESS")||!jsonObject.getBoolean("isSuccess")==true){
                throw  new CustomException(orderNo+"退款失败了");
            }*/
            UserAccount userAccount=new UserAccount();
            userAccount.setUserId(userId);
            userAccount.setAccount(new BigDecimal(money));
            boolean bl=userAccountMapper.addUserAccountMoney(userAccount)>0;
            if (bl==false){
                throw  new CustomException(orderNo+"下的"+ordersGoodsId+"退款失败了");
            }
            Long messageId=dto.getMessageId();
            transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
            record=addUpdateAccountMoneyDoNotOperateAccount(messageId, userId, money, type);
            dataSourceTransactionManager.commit(transactionStatus);
        }catch (Exception e){
            dataSourceTransactionManager.rollback(transactionStatus);
            throw  new CustomException(e.getMessage());
        }finally {
            boolean isLock = lock.isLocked();
            if (isLock) {
                lock.forceUnlock();
            }
        }
        return true;
    }

    @Override
    public List<UserAccount> listSysUserAccount(SysUserAccountDTO userAccountDTO) {
        PageHelper.startPage(userAccountDTO.getPageNum(),userAccountDTO.getPageSize());
        return userAccountMapper.selectAll();
    }


}
